package me.pppploi8.webmcs.http.jetty;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.HandlerWrapper;

import com.alibaba.fastjson.JSON;

public class CommonHandler extends HandlerWrapper {
	private Map<String, Object[]> urlMappingMap = new HashMap<>();//Map<Url, [method, class]>
	private List<Object[]> filterList = new ArrayList<>();//List<[regex, class]>
	
	public CommonHandler addUrlMapping(String prefix, String suffix, @SuppressWarnings("rawtypes") Class urlMapping){
		Method[] methods = urlMapping.getMethods();
		if (prefix == null){
			prefix = "/";
		}
		if (suffix == null){
			suffix = "";
		}
		for(Method m : methods){
			if(m.getDeclaringClass() == urlMapping){
				urlMappingMap.put(prefix + m.getName() + suffix, new Object[]{m, urlMapping});
			}
		}
		return this;
	}
	
	public CommonHandler addFilter(String regex, @SuppressWarnings("rawtypes") Class filter){
		filterList.add(new Object[]{regex, filter});
		return this;
	}

	@Override
	public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
			throws IOException, ServletException {
		for(Object[] obs : filterList){
			if(target.matches((String)obs[0])){
				try {
					@SuppressWarnings("rawtypes")
					HttpFilter filter = (HttpFilter)((Class)obs[1]).newInstance();
					if(!filter.handle(request, response)){
						return;
					}
				} catch (InstantiationException | IllegalAccessException e) {
					e.printStackTrace();
					response.sendError(500);
					return;
				}
			}
		}
		Object[] obs = urlMappingMap.get(target);
		if (obs != null){
			try {
				Method method = (Method) obs[0];
				@SuppressWarnings("rawtypes")
				Class c = (Class) obs[1];
				HttpUrlMapping h;
				h = (HttpUrlMapping) c.newInstance();
				h.setRequest(request);
				h.setResponse(response);
				Object result = method.invoke(h);
				if (result == null){
					return;
				}
				c = result.getClass();
				if (c == String.class){
					response.setCharacterEncoding("utf-8");
					response.setContentType("text/html;charset=utf-8");
					response.getWriter().write((String)result);
					response.getWriter().close();
					return;
				}else{
					response.setCharacterEncoding("utf-8");
					response.setContentType("text/html;charset=utf-8");
					response.getWriter().write(JSON.toJSONString(result));
					response.getWriter().close();
					return;
				}
			} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
				e.printStackTrace();
				response.sendError(500);
			}
		}else{
			response.sendError(404);
		}
	}
}
